package com.tarena.lbs.content.service.impl;

import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.model.Result;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.common.principle.UserPrinciple;
import com.tarena.lbs.common.utils.AuthenticationContextUtils;
import com.tarena.lbs.content.dao.repository.ArticleRepository;
import com.tarena.lbs.content.dao.repository.CategoryRepository;
import com.tarena.lbs.content.pojo.param.ArticleContentParam;
import com.tarena.lbs.content.pojo.po.ArticleCategoryPO;
import com.tarena.lbs.content.pojo.po.ArticleSearchPO;
import com.tarena.lbs.content.pojo.query.ArticleQuery;
import com.tarena.lbs.content.pojo.vo.ArticleActionPageResultVO;
import com.tarena.lbs.content.pojo.vo.ArticleActionVO;
import com.tarena.lbs.content.pojo.vo.ArticleStatsVO;
import com.tarena.lbs.content.pojo.vo.ArticleVO;
import com.tarena.lbs.content.service.ArticleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@Slf4j
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private ArticleRepository articleRepository;
    //categoryRepository
    @Autowired
    private CategoryRepository categoryRepository;


    @Override
    public void addArticle(ArticleContentParam param) throws BusinessException {
        log.debug("新增文章{}",param);
        ArticleSearchPO article=new ArticleSearchPO();
        BeanUtils.copyProperties(param, article);
        UserPrinciple userPrinciple= AuthenticationContextUtils.get();
        log.debug("新增文章用户信息：{}",userPrinciple);
        if(userPrinciple ==null){
            throw new BusinessException();
        }
        Integer userId = userPrinciple.getId();
        article.setCreateTime(new Date());
            article.setUserId(userId);
            article.setArticleUsername(userPrinciple.getNickname());

        if (article.getLatitude() != null && article.getLongitude() != null) {
            String geoPoint=article.getLatitude() + "," + article.getLongitude();
            article.setLocation(geoPoint);
        }else{
            article.setLocation(null);
        }
        article.setLikeCount(0);
        article.setFavoriteCount(0);
        article.setAccessCount(0);

        articleRepository.saveArticle(article);
    }

    @Override
    public PageResult<ArticleVO> pageList(ArticleQuery query) {
        return articleRepository.findArticle(query);
    }

    @Override
    public void updateArticle(ArticleContentParam param) throws BusinessException, IllegalAccessException {
        if(param.getId()==null){
            throw new IllegalAccessException("文章Id不能为空");
        }
        log.debug("更新文章,ID:{},参数：{}",param.getId(),param);

        ArticleSearchPO existingArticle=articleRepository.findArticleById(String.valueOf(param.getId()))
                .orElseThrow(() -> new BusinessException());

        if(param.getArticleTitle() !=null){
            existingArticle.setArticleTitle(param.getArticleTitle());
        }

        if(param.getArticleCategoryId() !=null){
            ArticleCategoryPO category=categoryRepository.findById(param.getArticleCategoryId())
                    .orElseThrow(()->new BusinessException());
            existingArticle.setArticleCategoryId(category.getId());

        }
        if(param.getArticleLabel() !=null){
            existingArticle.setArticleLabel(param.getArticleLabel());
        }
        if(param.getArticleDigest() !=null){
            existingArticle.setArticleDigest(param.getArticleDigest());
        }
        if(param.getArticleCover() !=null){
            existingArticle.setArticleCover(param.getArticleCover());
        }
        if(param.getArticleMainPic() !=null){
            existingArticle.setArticleMainPic(param.getArticleMainPic());
        }
        if(param.getArticleDetail() !=null){
            existingArticle.setArticleDetail(param.getArticleDetail());
        }
        if(param.getShopId() !=null){
            existingArticle.setShopId(param.getShopId());
        }
        if(param.getActivityWord() !=null){
            existingArticle.setActivityWord(param.getActivityWord());
        }
        if(param.getActivityId() !=null){
            existingArticle.setActivityId(param.getActivityId());
        }
        if(param.getLatitude() != null && param.getLongitude() != null){
            log.debug("接受经纬度,更新位置信息");

            existingArticle.setLatitude(param.getLatitude());
            existingArticle.setLongitude(param.getLongitude());

            existingArticle.setLocation(param.getLatitude()+","+param.getLongitude());
        }
        if(param.getArticleStatus() !=null){
            existingArticle.setArticleStatus(param.getArticleStatus());
        }
        existingArticle.setUpdateTime(new Date());

        articleRepository.updateArticle(existingArticle);
        log.info("更新文章成功,{}",existingArticle.getId());
    }

    @Override
    public void deleteArticle(String id) throws IllegalAccessException {
        if(id ==null || id.isEmpty()){
            log.warn("删除的文章不存在,Id：{}",id);
            throw new IllegalAccessException("删除文章,Id不能为空");
        }
        articleRepository.deleteArticleById(id);
        articleRepository.deleteArticleStatsFromRedis(id);
        log.info("文章删除成功,ID:{}",id);
    }

    @Override
    public ArticleVO articleDetail(String id) throws IllegalAccessException {
        if(id ==null || id.isEmpty()){
            throw new IllegalAccessException("查看文章详情,id不能为空");

        }
        log.info("根据ID查询文章详情,ID:{}",id);
        ArticleSearchPO articleSearchPO=articleRepository.findArticleById(id).orElse(null);

        if(articleSearchPO==null){
            log.debug("查询的文章不存在,ID:{}",id);
            return null;
        }
        articleRepository.incrementArticleStatInRedis(id,"accessCount",1);

        ArticleVO articleVO=new ArticleVO();
        BeanUtils.copyProperties(articleSearchPO,articleVO);
        articleVO.setId(Integer.valueOf(id));

        ArticleStatsVO statsFromRedis =articleRepository.getArticleStatsFromRedis(id);

        if(statsFromRedis !=null){
            log.debug("获取文章统计信息,{}",statsFromRedis);
            articleVO.setAccessCount(statsFromRedis.getAccessCount());
            articleVO.setFavoriteCount(statsFromRedis.getFavoriteCount());
            articleVO.setLikeCount(statsFromRedis.getLikeCount());
        }else{
            log.debug("缓存未命中,ID:{},准备回填缓存",id);
            ArticleStatsVO statsToReFill =new ArticleStatsVO();
            statsToReFill.setLikeCount(articleVO.getLikeCount());
            statsToReFill.setFavoriteCount(articleVO.getFavoriteCount());
            statsToReFill.setAccessCount(articleVO.getAccessCount());
            articleRepository.refillArticleStatsToRedis(id,statsToReFill);
            log.info("缓存回填成功,id：{}",id);
        }
        log.info("文章详情查询成功,ID:{}",id);
        return articleVO;
    }

    @Override
    public void handleAction(ArticleContentParam articleContentParam) throws BusinessException, IllegalAccessException {
        UserPrinciple userPrinciple =AuthenticationContextUtils.get();
        if(userPrinciple==null) {
            throw new BusinessException();
        }
        Integer actionUserId=userPrinciple.getId();
        ArticleVO article=articleDetail(String.valueOf(articleContentParam.getId()));
        if(article==null){
            log.warn("Attempted to act on a non-existent article,Id:{}",articleContentParam.getId());
            throw new BusinessException();
        }
//        UserVO actionUser=actionUserResult.getData();


        // 4. 更新Redis中的统计数据 (这部分逻辑不变)
//        String fieldToIncrement = mapActionTypeToRedisField(articleContentParam.getAction());
//        if (fieldToIncrement != null) {
//            articleRepository.incrementArticleStatInRedis(String.valueOf(articleContentParam.getId()), fieldToIncrement, 1L);
//            log.info("User {} performed action {} on article ID: {}. Redis count incremented.", actionUserId, fieldToIncrement, param.getId());
//        }

        ArticleSearchPO actionPO =new ArticleSearchPO();

        BeanUtils.copyProperties(articleContentParam,actionPO);
        actionPO.setCreateTime(new Date());


        articleRepository.addArticleAction(actionPO);
        log.info("User {}'s action on article ID: {} has been saved to Elasticsearch.",actionUserId,articleContentParam.getId());

    }

    @Override
    public Result<ArticleActionPageResultVO> getBehaviorLists(ArticleQuery query) throws BusinessException {
        log.debug("用户行为分页查询:{}", query);

        ArticleActionPageResultVO resultVO = new ArticleActionPageResultVO();

        // 场景一：查询指定文章下的行为列表 (前端文章详情页需要这个)
        if (query.getActivityId() != null) {

            // 如果前端指定了action (比如只想看评论)，就用前端的；否则默认查评论
            int actionType = (query.getActivityId() != null) ? query.getActivityId() : 3;

            // 调用我们 Repository 中【新写】的方法
            PageResult<ArticleActionVO> commentResult = articleRepository.findBehaviorsByArticleId(String.valueOf(query.getActivityId()), actionType, query);

            resultVO.setCommentFuturePageResult(commentResult);
            // 其他两种行为返回空结果
            PageResult<ArticleActionVO> emptyResult = new PageResult<>();
            emptyResult.setTotal(0L); // <<<--- 必须设置 total 为 0，避免 NullPointerException
            emptyResult.setObjects(Collections.emptyList()); // <<<--- 设置一个空的列表
            emptyResult.setPageNo(query.getPageNo()); // 保持分页信息一致
            emptyResult.setPageSize(query.getPageSize());
            resultVO.setLikeFuturePageResult(emptyResult);
            resultVO.setCollectFutureOPageResult(emptyResult);

        }
        // 场景二：查询指定用户的行为列表 (保留原有逻辑，用于"我的主页"等功能)
        else {
            Integer targetUserId = query.getUserId();
            if (targetUserId == null) {
                UserPrinciple user = Optional.ofNullable(AuthenticationContextUtils.get())
                        .orElseThrow(() -> new BusinessException());
                targetUserId = user.getId();
            }

            // 这里的 ArticleQuery 仅用于传递分页信息，虽然不规范但暂时维持原样以减少改动
            ArticleQuery legacyQuery = new ArticleQuery();
            legacyQuery.setPageNo(query.getPageNo());
            legacyQuery.setPageSize(query.getPageSize());

            // 调用我们 Repository 中【重命名】后的方法
            PageResult<ArticleActionVO> likeResult = articleRepository.findBehaviorsByUserId(targetUserId, 1, legacyQuery);
            PageResult<ArticleActionVO> collectResult = articleRepository.findBehaviorsByUserId(targetUserId, 2, legacyQuery);
            PageResult<ArticleActionVO> commentResult = articleRepository.findBehaviorsByUserId(targetUserId, 3, legacyQuery);

            resultVO.setLikeFuturePageResult(likeResult);
            resultVO.setCollectFutureOPageResult(collectResult);
            resultVO.setCommentFuturePageResult(commentResult);
        }

        return new Result<>(resultVO);
    }

    @Override
    public Set<String> articleabels(ArticleQuery query) {
        return articleRepository.findUniqueLabelsByQuery(query);
    }
    
    @Override
    public PageResult<ArticleVO> pageResult(ArticleQuery query){
        log.debug("文章分页查询：{}",query);
        PageResult<ArticleVO>voPage=articleRepository.findArticle(query);

        List<ArticleVO> vos=voPage.getObjects();
        if(vos== null || vos.isEmpty()){
            return voPage;
        }
        log.debug("查询完成,处理缓存逻辑");
        List<String> articleIds = new ArrayList<>();
        for (ArticleVO articleVO : vos) {
            Integer id = articleVO.getId();
            articleIds.add(String.valueOf(id));
        }
        Map<String,ArticleStatsVO>redisStatsMap=articleRepository.getBatchArticleStatsFromRedis(articleIds);
        Map<String,ArticleStatsVO>refillMap=new HashMap<>();

        for(ArticleVO vo : vos){
            ArticleStatsVO redisStats=redisStatsMap.get(vo.getId());
            if(redisStats !=null){
                vo.setLikeCount(redisStats.getLikeCount());
                vo.setFavoriteCount(redisStats.getFavoriteCount());
                vo.setAccessCount(redisStats.getAccessCount());
            }else{
                ArticleStatsVO esStats=new ArticleStatsVO();
                esStats.setLikeCount(vo.getLikeCount());
                esStats.setFavoriteCount(vo.getFavoriteCount());
                esStats.setAccessCount(vo.getAccessCount());
                refillMap.put(String.valueOf(vo.getId()),esStats);
            }
        }
        if(!refillMap.isEmpty()){
            log.info("列表查询发现{} 个 缓存为命中",refillMap.size());
            articleRepository.refillBatchArticleStatsToRedis(refillMap);
        }
        return voPage;

    }
}